package simulation;

import java.util.LinkedList;

public class ReservationStation {
	
	static LinkedList<ReservationStationEntry> RS;
	//static String[] operations;
	static int size;

	static int addsubCycles;
	static int mulCycles;
	static int divCycles;
	
	public ReservationStation(){}
	
	public ReservationStation(int isize, int iaddsubCycles, int imulCycles, int idivCycles){
		
		size = isize;
		RS = new LinkedList<ReservationStationEntry>();
		//operations = new String[isize];
	
		addsubCycles = iaddsubCycles;
		mulCycles = imulCycles;
		divCycles = idivCycles;
				
	}
	
	public static boolean newRSEntry(ReservationStationEntry r){

		if(size != 0){
			size--;
			RS.addLast(r);
			return true;
		}
		
		return false;
	}
	
	public static void newRSEntry(String instruction){
		
		String[] inst = instruction.split(" ");
		String opcode = inst[0];
		String[] operands = inst[1].split(",");
		
		if(size != 0){
			size--;
			
			ReservationStationEntry rse=new ReservationStationEntry(-1 , opcode,"NotReady",Character.toString(operands[0].charAt(1)),Character.toString(operands[0].charAt(1)),Character.toString(operands[0].charAt(1)), true, true, "-1", "-1"); 	 
			
			for (int i = 0; i < RS.size(); i++) {
				if(RS.get(i).resultOperand.equals(operands[1].charAt(1)))
					rse.sourceReady1=false;
				if(RS.get(i).resultOperand.equals(operands[2].charAt(1)))
					rse.sourceReady2=false;	
			
			}
			
			if(opcode.startsWith("Mul"))
				rse.cyclesLeft = mulCycles;
			
			else if(opcode.startsWith("Add") || opcode.startsWith("Sub"))
				rse.cyclesLeft = addsubCycles;
			
			else if(opcode.startsWith("Div"))
				rse.cyclesLeft = divCycles;
			
			
			RS.add(rse);
		}
	
	}
	
	public static void check(){
		
		for(int i = 0; RS.get(i) != null; i++){
				
			if(RS.get(i).done){
				
				remove(i);	
				
				size++;
			}
			
			else {
				
				if(RS.get(i).status.equalsIgnoreCase("execute"))
					RS.get(i).cyclesLeft--;
				
			}
		}
	}
	
	public static void remove(int location){
		
		boolean only = true;
		
		for(int i = 0; i < RS.size(); i++){
			
			if(RS.get(i).sourceOperand1 == RS.get(location).resultOperand){
				RS.get(i).sourceReady1 = true;
				
			}
			if(RS.get(i).sourceOperand2 == RS.get(location).resultOperand){
				RS.get(i).sourceReady2 = true;
				
			}
			if(RS.get(i).resultOperand == RS.get(location).resultOperand)
				only = true;
		}
		
		if(only)
			ROB.updateRegisterValue(RS.get(location).instructionID, (int)RS.get(location).resultOperand.charAt(0));
		
	}

	boolean hasPlace(String instruction){
		String[] inst = instruction.split(" ");
		String opcode = inst[0];
		
		
		if(!(opcode.equals("BEQ") || opcode.equals("JMP")
							|| opcode.equals("JALR") || opcode.equals("RET")||  opcode.equals("SW"))){
		if(size>0){
			size--;
			return true;
		}else{
			return false;
		}
		
		}
	return true;
			
	}


	@Override
	public String toString(){
		
		String output = "";
		
		for(int i = 0; i < RS.size(); i ++)
			output += "Station " + i + ": " + RS.get(i).toString() + " \n" ;

		
		return output;
	}
	
}
